from pyjvm.instructions.common import BranchInstruction, branch
from pyjvm.runtime.thread import Frame


class IFEQ(BranchInstruction):

    def execute(self, frame: Frame):
        if frame.operand_stack.pop() == 0:
            branch(frame, self.offset)


class IFGE(BranchInstruction):

    def execute(self, frame: Frame):
        if frame.operand_stack.pop() >= 0:
            branch(frame, self.offset)


class IFGT(BranchInstruction):

    def execute(self, frame: Frame):
        if frame.operand_stack.pop() > 0:
            branch(frame, self.offset)


class IFLE(BranchInstruction):

    def execute(self, frame: Frame):
        if frame.operand_stack.pop() <= 0:
            branch(frame, self.offset)


class IFLT(BranchInstruction):

    def execute(self, frame: Frame):
        if frame.operand_stack.pop() < 0:
            branch(frame, self.offset)


class IFNE(BranchInstruction):

    def execute(self, frame: Frame):
        if frame.operand_stack.pop() != 0:
            branch(frame, self.offset)


class IF_ICMPEQ(BranchInstruction):

    def execute(self, frame: Frame):
        stack = frame.operand_stack
        if stack.pop() == stack.pop():
            branch(frame, self.offset)


class IF_ICMPNE(BranchInstruction):

    def execute(self, frame: Frame):
        stack = frame.operand_stack
        val2 = stack.pop()
        val1 = stack.pop()
        if val1 != val2:
            branch(frame, self.offset)


class IF_ICMPLT(BranchInstruction):

    def execute(self, frame: Frame):
        stack = frame.operand_stack
        val2 = stack.pop()
        val1 = stack.pop()
        if val1 < val2:
            branch(frame, self.offset)


class IF_ICMPLE(BranchInstruction):

    def execute(self, frame: Frame):
        stack = frame.operand_stack
        val2 = stack.pop()
        val1 = stack.pop()
        if val1 <= val2:
            branch(frame, self.offset)


class IF_ICMPGT(BranchInstruction):

    def execute(self, frame: Frame):
        stack = frame.operand_stack
        val2 = stack.pop()
        val1 = stack.pop()
        if val1 > val2:
            branch(frame, self.offset)


class IF_ICMPGE(BranchInstruction):

    def execute(self, frame: Frame):
        stack = frame.operand_stack
        val2 = stack.pop()
        val1 = stack.pop()
        if val1 >= val2:
            branch(frame, self.offset)


class IF_ACMPEQ(BranchInstruction):

    def execute(self, frame: Frame):
        stack = frame.operand_stack
        val2 = stack.pop()
        val1 = stack.pop()
        if val1 is val2:
            branch(frame, self.offset)


class IF_ACMPNE(BranchInstruction):

    def execute(self, frame: Frame):
        stack = frame.operand_stack
        val2 = stack.pop()
        val1 = stack.pop()
        if val1 is not val2:
            branch(frame, self.offset)


class IFNONNULL(BranchInstruction):

    def execute(self, frame: Frame):
        ref = frame.operand_stack.pop()
        if ref is not None:
            branch(frame, self.offset)


class IFNULL(BranchInstruction):

    def execute(self, frame: Frame):
        ref = frame.operand_stack.pop()
        if ref is None:
            branch(frame, self.offset)


__all__ = ['IF_ACMPEQ', 'IF_ACMPNE', 'IF_ICMPEQ', 'IF_ICMPGE', 'IF_ICMPGT', 'IF_ICMPLE',
           'IF_ICMPLT', 'IF_ICMPNE', 'IFEQ', 'IFGE', 'IFGT', 'IFLE', 'IFLT',
           'IFNE', 'IFNONNULL', 'IFNULL']
